<?php

namespace app\wechat\models;

use Exception;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Exceptions\LocalCacheException;
use yii\base\InvalidArgumentException;
use app\wechat\core\BaseModel;
use cm;
use Yii;
use yii\helpers\Url;

class OrderModel extends BaseModel
{
	/*
	*购票须知
	*/
	public function actionBuynotice(){
		$resdata = $this->getNoticeData('sys_buy_notice');
		Cm::$res->susess($resdata);
	}

	/*
	*退票须知
	*/
	public function actionRetreatnotice(){
		$resdata = $this->getNoticeData('sys_retreat_notice');
		Cm::$res->susess($resdata);
	}

	/*
	*开单
	*/
	public function actionAddorder(){
		$id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
		$contacts = Cm::$req->post('contacts', ['null', 'empty', 'default' => '']);
		$contacts_num = (int)Cm::$req->post('contacts_num', ['null', 'empty', 'default' => 0]);
		$contactsarr = empty($contacts) ? [] : json_decode($contacts,true);
		if(empty($contactsarr)){
			Cm::$res->error("请添加乘客信息");
		}
		if($contacts_num != count($contactsarr)){
			Cm::$res->error("乘客人数信息错误");
		}
		$time = time();
		$timestr = date("Y-m-d H:i:s",$time);
		$shiftinfo = Cm::$db->one("SELECT a.id,a.circuit_id,a.presaletime,a.closingtime,a.ticket_price,b.name FROM shift a INNER JOIN circuit b ON a.circuit_id=b.id WHERE a.id={$id} AND a.status=1 AND b.status=1");
		if(empty($shiftinfo)){
			Cm::$res->error("没有找到该班次");	
		}
		if(strtotime($shiftinfo['closingtime'])<$time){
			Cm::$res->error("该班次已停售");		
		}
		$user = Cm::$db->one("SELECT id,telephone FROM user WHERE openid='{$this->openid}'");
		if(empty($user['id'])){
			Cm::$res->error('参数错误');	
		}
		$isok = 1;
		$telephone = '';
		$contactsids = [];
		$isrepeat = 0;
		foreach ($contactsarr as $key => $value) {
			if(empty($value['name']) || empty($value['telephone']) || empty($value['idcard']) || empty($value['id']) || empty($value['contacts_id'])){
				$isok = 0;
				break;
			}
			if(!in_array($value['contacts_id'], $contactsids)){
				$contactsids[] = $value['contacts_id'];
			}else{
				$isrepeat = 1;
				break;
			}
			$telephone = $key == 0 ? $value['telephone'] : $telephone;
		}
		if($isok == 0){
			Cm::$res->error('乘客信息不正确');	
		}
		if($isrepeat == 1){
			Cm::$res->error('不能重复添加乘客');	
		}

		$config = Cm::$db->all("SELECT `key`,`value` FROM config_setting WHERE `group`='sys' AND `key` IN ('sys_service_charge','sys_premium') "); 
		$service_charge = 0;
		$premium = 0;
		if(!empty($config)){
			foreach ($config as $key => $vs) {
				if($vs['key'] == 'sys_service_charge'){
					$service_charge = floatval($vs['value']*$contacts_num);	
				}else if($vs['key'] == 'sys_premium'){
					$premium = floatval($vs['value']*$contacts_num);	
				}
			}
		}
		$price = floatval($shiftinfo['ticket_price']*$contacts_num);
		$order_price = $price + $premium + $service_charge;

		$order_number = $this->getorderanumber($id,$shiftinfo['circuit_id'],$timestr);
		$order_number = "M".$order_number;
		$orderdata = [
			'order_number' => $order_number,
			'shift_id'=> $id,
			'circuit_id' => $shiftinfo['circuit_id'],
			'order_status' => 0,
			'ridership' => count($contactsarr),
			'order_price' => $order_price,
			'price' => $price,
			'premium' => $premium,
			'service_charge' => $service_charge,
			'source' => 1,
			'user_id' => $user['id'],
			'user_telephone' => empty($user['telephone']) ? $telephone : $user['telephone'],
			'status'=>1,
			'addtime' => $timestr,
			'updatetime' => $timestr
		];
		$orderid = Cm::$db->insert("order", $orderdata);
		$config = Yii::$app->params['wechat']['open'];
		$paySdk = Cm::$libs->wechat->pay($config['appid']);
		$goods = [
            "body" => '商品购买',
            "attach" => 'order',
            "out_trade_no" => $order_number,
            "total_fee" => $order_price * 100,
            "goods_tag" => $shiftinfo['name'],
            "openid" => $this->openid,
            "notify_url" => BASE_URL . Url::to(['/wechat/order/notify'])
        ];
        $payRes = $paySdk->jspay($goods);
        if (!$payRes['flag']) {
            Cm::$res->error($payRes['msg']);
        }

		if($orderid){
			foreach ($contactsarr as $key => $value) {
				$mdata = [
					'order_id'=> $orderid,
					'shift_id'=> $id,
					'circuit_id' => $shiftinfo['circuit_id'],
					'user_id'=> $user['id'],
					'contacts_id' => $value['contacts_id'],
					'name' => $value['name'],
					'telephone' => $value['telephone'],
					'id_card' => $value['idcard'],
					'status' => 1,
					'addtime' => $timestr,
					'updatetime' => $timestr
				];
				Cm::$db->insert("order_passenger", $mdata);
			}	
			$this->addordercode($orderid);
			Cm::$res->susess(['id'=>$orderid,'order_number'=>$order_number,'price'=>$price,'order_price'=>$order_price,'premium'=>$premium,'service_charge'=>$service_charge,'pay' => $payRes['data']],'保存成功');
		}else{
			Cm::$res->error('保存失败');		
		}
	}

	/*
	*订单待支付支付
	*/
	public function actionPayorder(){
		$this->refreshorder();
		$id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
		$where = " a.id={$id} AND u.openid='{$this->openid}'";
		$info = Cm::$db->one("SELECT a.id,a.order_number,a.order_price,a.order_status,a.status,c.name,a.pay_status
				FROM `order` a 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where}");
		if(empty($info)){
			Cm::$res->error("订单不存在");
		}
		if($info['order_status'] == 5){
			Cm::$res->error("订单已失效,无法在支付");	
		}
		if($info['status'] != 1){
			$strarr = [0=>'取消',2=>'删除',3=>'改签',4=>'退款'];
			Cm::$res->error("订单已".$strarr[$info['status']].",无法在支付");	
		}
		if($info['order_status'] != 0){
			Cm::$res->error("订单已支付,无法在支付");	
		}

		if($info['pay_status'] != 0){
			Cm::$res->error("订单已支付,无法在支付");	
		}

		$config = Yii::$app->params['wechat']['open'];
		$paySdk = Cm::$libs->wechat->pay($config['appid']);
		$goods = [
            "body" => '商品购买',
            "attach" => 'order',
            "out_trade_no" => $info['order_number'],
            "total_fee" => $info['order_price'] * 100,
            "goods_tag" => $info['name'],
            "openid" => $this->openid,
            "notify_url" => BASE_URL . Url::to(['/wechat/order/notify'])
        ];
        $payRes = $paySdk->jspay($goods);
        if (!$payRes['flag']) {
            Cm::$res->error($payRes['msg']);
        }
        Cm::$res->susess(['pay' => $payRes['data']],'');
	}

	/*
	*订单支付回调
	*/
	public function actionNotify(){
		$xml = "";
        if (isset($GLOBALS['HTTP_RAW_POST_DATA'])){
            $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        }

        $this->notifylog($xml,'notify-GLOBALS');

        if(empty($xml)){
        	$xml = file_get_contents('php://input');
			$this->notifylog($xml,'notify-input');        	
        }

        if (empty($xml)) {
            $this->notifylog("支付回调无参数");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!$data) {
            $this->notifylog("没有数据");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }

        if (!$this->checkSign($data)) {
            $this->notifylog("签名失败");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>";
            exit;
        }

        $flag = false;
        if (isset($data['result_code']) && isset($data['return_code'])) {
            if ($data['result_code'] == "SUCCESS" && $data['return_code'] == "SUCCESS") {
                $number = isset($data['out_trade_no']) ? $data['out_trade_no'] : '';
                if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,pay_status FROM `order` WHERE order_number='{$number}' AND pay_status=0");
                    if (isset($info['id'])) {
                        if ($info['pay_status']==0) {
                            //更改支付状态
                            $time = date("Y-m-d H:i:s",time());
                            $pay_price = $data['cash_fee']/100;
                            Cm::$db->update("order", ["order_status"=>1,"updatetime"=>$time,"pay_type"=>1,"pay_status" => 1, "pay_time" => $time,'pay_price'=>$pay_price], "id={$info['id']}");

                            //发送购买成功通知
                            $TemplateData = [
					            'openid' => $data['openid'],
					            'order_id' => $info['id']
					        ];
							Cm::$libs->wechat->sendTemplate('order',$TemplateData);
                        }else{
                        	$this->notifylog($data,'notify-pay_status');		
                        }
                    }else{
                    	$this->notifylog($data,'notify-id');	
                    }
                }else{
                	$this->notifylog($data,'notify-number');
                }
            }else{
            	$this->notifylog($data,'notify-SUCCESS');
            }
        }else{
        	$this->notifylog($data,'notify-isset');
        }

        echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        exit;
	}

	/*
	*获取我的订单
	*/
	public function actionOrderlist(){
		$this->refreshorder();
		$page = Cm::$req->post('page', ['null', 'empty', 'default' => 1]);
		$limit = Cm::$req->post('limit', ['null', 'empty', 'default' => 10]);
		$type = Cm::$req->post('type', ['null', 'empty', 'default' => 0]);
		$where = " a.status!=2 AND u.openid='{$this->openid}'";
		$time = time();
		$nowtime = date("Y-m-d H:i:s",$time);
		$time15 = $time+900; 
		$etime = date("Y-m-d H:i:s",$time+900);
		if($type == 1){
			$where .= " AND a.order_status=0 ";
		}elseif($type == 2){
			$where .= " AND (a.order_status=1 OR (a.order_status=2 && b.departuretime>'{$etime}') ) ";
		}elseif($type == 3){
			$where .= " AND a.order_status IN (3,4) ";
		}elseif($type == 4){
			$where .= " AND a.order_status=5";
		}elseif($type == 5){
			$where .= " AND a.order_status=5 AND a.status=4";
		}elseif ($type == 6) {
			$where .= " AND a.order_status=2 AND b.departuretime>='{$nowtime}' AND b.departuretime<='{$etime}' ";
		}
		$sql = "SELECT a.id,a.order_number,a.order_price,a.order_status,a.status,coa.name AS citysname,coa.id AS citysid,cob.name AS cityename,cob.id AS cityeid,sa.name AS sitesname,sa.id AS sitesid,sb.name AS siteename,sb.id AS siteeid,b.departuretime,ridership AS ticketnum,a.circuit_id,a.codeimg,a.codenum,a.refund_status
				FROM `order` a 
				LEFT JOIN shift b ON a.shift_id=b.id 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN open_city coa ON coa.code=c.city_scode 
				LEFT JOIN open_city cob ON cob.code=c.city_ecode
				LEFT JOIN site sa ON sa.id=c.site_sid 
				LEFT JOIN site sb ON sb.id=c.site_eid 
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where} ORDER BY a.order_status ASC,b.departuretime ASC";
		$resdata = Cm::$db->paging($sql,$page, $limit);	
		foreach ($resdata['data'] as $key => &$value) {
			$departuretime = strtotime($value['departuretime']);
			if($value['order_status'] == 2 && $departuretime>=$time && $departuretime<= $time15){
				$value['order_status'] = 6;
			}
			$value['day'] = date("m月d日",$departuretime);
			$value['hour'] = date("H:i",$departuretime);
			$exitchange = $this->checkchange($value['id'],$value['departuretime'],$nowtime,$value['circuit_id']);
			$value['ischange'] = $exitchange['status'] == 1 && in_array($value['order_status'], [1,2]) && $value['status']==1 ? 1:0;
			if(empty($value['codeimg']) && $value['order_status'] != 0 && $value['order_status'] !=5){
				$codedata = $this->addordercode($value['id']);
				$value['codeimg'] = $codedata['codeimg'];
				$value['codenum'] = $codedata['codenum'];
			}
			$value['codeimg'] = empty($value['codeimg']) ? '' : $value['codeimg'];
		}
		Cm::$res->susess($resdata);
	}

	/*
	*取消订单
	*/
	public function actionCancel(){
		$id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
		$order = Cm::$db->one("SELECT id,status,order_status FROM `order` WHERE id={$id}");
		if(empty($order)){
			Cm::$res->error("订单不存在");
		}
		if($order['status'] == 1 && $order['order_status'] == 0){
			$time = date("Y-m-d H:i:s",time());
			$mdata = [
				'status' => 0,
				'order_status' => 5,
				'updatetime' => $time,
				'canceltime' => $time
			];
			Cm::$db->update("order", $mdata," id={$id}");
			Cm::$res->susess([],"取消订单成功");	
		}else{
			$msg = '';
			if($order['status'] == 1){
				switch ($order['order_status']) {
					case 1:
						$msg = "订单已支付";
						break;
					case 2:
						$msg = "订单已支付";
						break;	
					case 3:
						$msg = "订单已发车";
						break;
					case 4:
						$msg = "订单已完成";
						break;	
				}
			}else if($order['status'] == 2){
				$msg = "订单已删除";
			}else if($order['status'] == 0){
				$msg = "订单已取消";
			}else if($order['status'] == 3){
				$msg = "订单已改签";
			}else if($order['status'] == 4){
				$msg = "订单已退款";
			}
			$msg .= $msg==''?'订单当前状态不能进行取消操作':",不能在进行取消操作";
			Cm::$res->error($msg);
		}
	}

	/*
	*订单详情
	*/
	public function actionInfo(){
		$this->refreshorder();
		$id = (int)Cm::$req->post('id', ['null', 'empty', 'default' => 0]);
		$where = " a.id={$id} AND u.openid='{$this->openid}'";
		$info = Cm::$db->one("SELECT a.id,a.order_number,a.circuit_id,a.order_price,a.price,a.premium,a.service_charge,a.order_status,a.status,b.type,c.mileage,coa.name AS citysname,coa.id AS citysid,cob.name AS cityename,cob.id AS cityeid,sa.name AS sitesname,sa.id AS sitesid,sb.name AS siteename,sb.id AS siteeid,b.departuretime,a.codenum,a.codeimg,a.refund_status,c.s_address,c.e_address 
				FROM `order` a 
				LEFT JOIN shift b ON a.shift_id=b.id 
				LEFT JOIN circuit c  ON a.circuit_id=c.id
				LEFT JOIN open_city coa ON coa.code=c.city_scode 
				LEFT JOIN open_city cob ON cob.code=c.city_ecode
				LEFT JOIN site sa ON sa.id=c.site_sid 
				LEFT JOIN site sb ON sb.id=c.site_eid 
				LEFT JOIN user u ON u.id=a.user_id
				WHERE {$where}");
		if(empty($info)){
			Cm::$res->error("订单不存在");
		}
		$config = Cm::$db->all("SELECT `key`,`value` FROM config_setting WHERE `group`='sys' AND `key` IN ('sys_service_charge','sys_premium') "); 
		$service_charge = 0;
		$premium = 0;
		if(!empty($config)){
			foreach ($config as $key => $vs) {
				if($vs['key'] == 'sys_service_charge'){
					$service_charge = floatval($vs['value']);	
				}else if($vs['key'] == 'sys_premium'){
					$premium = floatval($vs['value']);	
				}
			}
		}
		$info['one_service_charge'] = $service_charge;
		$info['one_premium'] = $premium;
		$departuretime = strtotime($info['departuretime']);
		$info['day'] = date("m月d日",$departuretime);
		$info['hour'] = date("H:i",$departuretime);
		$info['typestr'] = $info['type'] == 1 ? "固定班":"流动班";
		$passenger = Cm::$db->all("SELECT name,telephone,id_card AS idcard,seat_number FROM order_passenger WHERE order_id={$id} AND status=1");
		$seat_number = [];
		foreach ($passenger as $key => &$value) {
			$idcardlen = strlen($value['idcard']);
			$value['idcard'] = $idcardlen==15?substr_replace($value['idcard'],"******",4,6):($idcardlen==18?substr_replace($value['idcard'],"*********",4,9):$value['idcard']);
			if(!empty($value['seat_number'])){
				$seat_number[] = $value['seat_number']."号";
			}
		}
		$car = Cm::$db->one("SELECT b.plate,c.username AS name,c.account AS telephone FROM order_car a
							LEFT JOIN car b ON b.id=a.car_id
							LEFT JOIN sys_manager c ON c.id=a.inspector
							WHERE a.order_id={$id} AND a.status=1");
		if(!empty($seat_number)){
			$car['seat_number'] = implode("  ", $seat_number);
		}
		$car = empty($car) ? [] : $car;
		$exitchange = $this->checkchange($info['id'],$info['departuretime'],date("Y-m-d H:i:s",time()),$info['circuit_id']);
		$info['ischange'] = $exitchange['status'] == 1 && in_array($info['order_status'], [1,2]) && $info['status']==1? 1:0;
		Cm::$res->susess(['info'=>$info,'passenger'=>$passenger,'car'=>$car]);
	}

	/*
	*订单改签提交审核
	*/
	public function actionChange(){
		$order_id = (int)Cm::$req->post('order_id', ['null', 'empty', 'default' => 0]);
		$shift_id = (int)Cm::$req->post('shift_id', ['null', 'empty', 'default' => 0]);
		$order = Cm::$db->one("SELECT a.id,a.order_status,a.status,b.departuretime,a.circuit_id FROM `order` a LEFT JOIN shift b ON b.id=a.shift_id WHERE a.id={$order_id}");
		if(empty($order)){
			Cm::$res->error("订单未找打");
		}
		if($order['status'] == 1 && in_array($order['order_status'], [1,2])){
			$time = date("Y-m-d H:i:s",time());
			/*改签规则验证*/
			$exitchange = $this->checkchange($order['id'],$order['departuretime'],$time,$order['circuit_id']);
			if($exitchange['status'] == 0){
				$str = $exitchange['time'] == 0 ? "" : "发车前".$exitchange['time']."分钟";
				Cm::$res->error("订单".$str."无法进行改签操作");		
			}else if($exitchange['status'] == 3){
				Cm::$res->error("该订单行程已达到系统设置的最大改签次数".$exitchange['changenum']."次,无法进行改签操作");		
			}

			$mdata = [
				'order_id' => $order_id,
				'shift_id' => $shift_id,
				'first_order_id' => empty($exitchange['order_id']) ? $order_id : $exitchange['order_id'],
				'status' => 1,
				'addtime' => $time,
				'updatetime' => $time
			];
			$id = Cm::$db->insert("order_change_audit", $mdata);
			if($id){
				/*生成新订单*/
				$this->addneworder($id,$time);
				Cm::$res->susess([],"改签成功");
			}else{
				Cm::$res->error("改签失败");
			}
		}else{
			$msg = '';
			if($order['status'] == 1){
				switch ($order['order_status']) {
					case 0:
						$msg = "订单未支付";
						break;
					case 3:
						$msg = "订单已发车";
						break;
					case 4:
						$msg = "订单已完成";
						break;	
				}
			}else if($order['status'] == 2){
				$msg = "订单已删除";
			}else if($order['status'] == 0){
				$msg = "订单已取消";
			}else if($order['status'] == 3){
				$msg = "订单已改签";
			}else if($order['status'] == 4){
				$msg = "订单已退款";
			}
			$msg .= $msg==''?'订单当前状态不能进行改签操作':",不能在进行改签操作";
			Cm::$res->error($msg);
		}	
	}

	/*
	*订单退款
	*/
	public function actionRefund(){
		$order_id = (int)Cm::$req->post('order_id', ['null', 'empty', 'default' => 0]);
		$time = time();
		$order = Cm::$db->one("SELECT a.id,a.order_number,a.order_status,a.status,b.departuretime,a.circuit_id,a.pay_price 
								FROM `order` a 
								LEFT JOIN shift b ON b.id=a.shift_id 
								LEFT JOIN user u ON u.id=a.user_id 
								WHERE a.id={$order_id} AND u.openid='{$this->openid}'");
		if(empty($order)){
			Cm::$res->error("订单不存在");
		}
		if($order['status'] == 1 && in_array($order['order_status'], [1,2]) ){
			$timestr = date("Y-m-d H:i:s",$time);
			/*验证能否进行退票*/
			$exitisok = $this->checkrefund($order['departuretime'],$timestr,$order['circuit_id']);
			if($exitisok['status'] == 0){
				$str = $exitisok['time'] == 0 ? "" : "发车前".$exitisok['time']."分钟";
				Cm::$res->error("订单".$str."无法进行退票操作");		
			}
			/*是否有改签*/
			$haschange = $this->ischangeorder($order['id']);
			$order['pay_price'] = $haschange['status'] == 1 ? $haschange['pay_price'] : $order['pay_price'];
			$departuretime = strtotime($order['departuretime']);
			/*全款退*/
			$isall = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=6 AND  circuit_id={$order['circuit_id']} AND status=1");
			if(empty($isall)){
				$isall = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=6 AND  circuit_id=0 AND status=1");
				$alltimenum = empty($isall) ? 0 : (int)$isall['value'];
			}else{
				$alltimenum = (int)$isall['value'];
			}
        	$isok = 0;
			$refund_amount = $order['pay_price'];
			$refund_service = 0;
			if($alltimenum != 0){
				$alltime = strtotime("-".$alltimenum." day",$departuretime);
				if($time <= $alltime){
					/*全款退*/
					$isok = 1;
				}
			}
			
			/*部分退*/
			if($isok == 0){
	            /*部分*/
	            $isone = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=8 AND  circuit_id={$order['circuit_id']} AND status=1");
	            if(empty($isone)){
	                $isone = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=8 AND  circuit_id=0 AND status=1");
	            }
	            if(!empty($isone)){
	                $rule = json_decode($isone['value'],true);
	                foreach ($rule['start'] as $key => $value) {
	                    $starttime = $value == 1 ?  $departuretime : strtotime("-".$value." day",$departuretime);
	                    $endtime = strtotime("-".$rule['end'][$key]." day",$departuretime);
	                    $service = $rule['service'][$key]; 
	                    if($time >= $endtime && $time < $starttime) {
	                        $isok = 1;
	                    }
	                    if($isok == 1){
	                        $refund_service = sprintf("%.2f",$refund_amount*$service/100);
	                        $refund_amount = $refund_service > 0 ? sprintf("%.2f",$refund_amount-$refund_service) : $refund_amount;
	                        if($refund_amount>$order['pay_price']){
	                            $refund_amount = $order['pay_price'];
	                            $refund_service = 0;    
	                        }
	                        break;
	                    }
	                }
	            }
	        }
			$order['order_number'] = $haschange['status'] == 1 ? $haschange['order_number'] : $order['order_number'];
			/*退款单号*/
			$refund_number = "R".$order['order_number'];
			$config = Yii::$app->params['wechat']['open'];
			$paySdk = Cm::$libs->wechat->pay($config['appid']);
			$goods = [
	            "out_trade_no" => $order['order_number'],
	            "out_refund_no" => $refund_number,
	            "refund_fee" => $refund_amount*100,
	            "total_fee" => $order['pay_price'] * 100,
	            "notify_url" => BASE_URL . Url::to(['/wechat/order/refundnotify'])
	        ];
	        $res = $paySdk->orderrefund($goods);
			if($res['flag']){
				$mdata = [
					'status' => 4,
					'order_status' => 5,
					'updatetime' => $timestr,
					'refund_amount' => $refund_amount,
					'refund_service' => $refund_service,
					'refund_number' => $refund_number,
					'refund_time' => $timestr,
					'refund_status' => 0
				];
				Cm::$db->update("order", $mdata," id={$order_id}");
				Cm::$res->susess([],"退款申请成功");
			}else{
				Cm::$res->error($res['msg']);
			}
		}else{
			$msg = '';
			if($order['status'] == 1){
				switch ($order['order_status']) {
					case 0:
						$msg = "订单未支付";
						break;
					case 3:
						$msg = "订单已发车";
						break;
					case 4:
						$msg = "订单已完成";
						break;	
				}
			}else if($order['status'] == 2){
				$msg = "订单已删除";
			}else if($order['status'] == 0){
				$msg = "订单已取消";
			}else if($order['status'] == 3){
				$msg = "订单已改签";
			}else if($order['status'] == 4){
				$msg = "订单已退款";
			}
			$msg .= $msg==''?'订单当前状态不能进行退款操作':",不能在进行退款操作";
			Cm::$res->error($msg);
		}
	}

	/*退票回调*/
	public function actionRefundnotify(){
        $xml = file_get_contents('php://input');
		$this->notifylog($xml,'refundnotify-input'); 

        if (empty($xml)) {
            $this->notifylog("支付回调无参数","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!$data) {
            $this->notifylog("没有数据","refundnotify");
            echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
            exit;
        }
        if($data['return_code'] == 'SUCCESS'){
        	$req_info_xml = $this->refundDecrypt($data['req_info']);
        	libxml_disable_entity_loader(true);
        	$reqinfoarr = json_decode(json_encode(simplexml_load_string($req_info_xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        	if($reqinfoarr['refund_status'] == 'SUCCESS'){
        		$number = isset($reqinfoarr['out_refund_no']) ? $reqinfoarr['out_refund_no'] : '';
        		if (!empty($number)) {
                    $info = Cm::$db->one("SELECT id,refund_status FROM `order` WHERE refund_number='{$number}' AND refund_status=0");
                    if (isset($info['id'])) {
                        if ($info['refund_status']==0) {
                            //更改退款状态
                            $time = isset($reqinfoarr['success_time']) ? $reqinfoarr['success_time'] : date("Y-m-d H:i:s",time());
                            Cm::$db->update("order", ["refund_status"=>1,"refund_time"=>$time], "id={$info['id']}");

                            //发送退款成功通知
                            $TemplateData = [
					            'order_id' => $info['id'],
					        ];
							Cm::$libs->wechat->sendTemplate('refund',$TemplateData);
                        }else{
                        	$this->notifylog($reqinfoarr,'refundnotify-refund_status');		
                        }
                    }else{
                    	$this->notifylog($reqinfoarr,'refundnotify-id');	
                    }
                }else{
                	$this->notifylog($reqinfoarr,'refundnotify-number');
                }
        	}else{
        		$this->notifylog("没有数据","refundnotify-req_info");
        	}
        	echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        	exit;
        }else{
        	$this->notifylog("没有数据","refundnotify-FAIL");
        }
        echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数格式校验错误]]></return_msg></xml>";
        exit;
	}

	/*
    *改签生成新的订单
    */
    private function addneworder($auditid,$time){
        $order = Cm::$db->one("SELECT a.shift_id,b.circuit_id,b.ridership,b.order_price,b.price,b.premium,b.service_charge,b.source,b.user_id,b.user_telephone,b.id as order_id,b.order_status,b.status
                            FROM order_change_audit a 
                            LEFT JOIN `order` b ON b.id=a.order_id 
                            WHERE a.id={$auditid}");
        $contactsarr = Cm::$db->all("SELECT b.* FROM order_change_audit a LEFT JOIN order_passenger b ON b.order_id=a.order_id WHERE a.id={$auditid}");
        if(empty($contactsarr)){
        	Cm::$db->delete("order_change_audit","id={$auditid}");
            Cm::$res->error("改签失败,没有找打乘客信息");
        }
        $order_id = $order['order_id'];
        unset($order['order_id']);
        $order['order_status'] = 1;
        $order['status'] = 1;
        $order['addtime'] = $time;
        $order['updatetime'] = $time;
        $order_number = $this->getorderanumber($order['shift_id'],$order['circuit_id'],$time);
        $order['order_number'] = "M".$order_number;
        $changeid = Cm::$db->insert("order", $order);
        if($changeid){
            $this->addordercode($changeid);
            Cm::$db->update("order",['order_status'=>5,'status'=>3,'updatetime'=> $time],"id={$order_id}");
            Cm::$db->update("order_passenger",['status'=>0,'updatetime'=> $time],"order_id={$order_id}");
            foreach ($contactsarr as $key => $value) {
                $mdata = [
                    'order_id'=> $changeid,
                    'shift_id'=> $order['shift_id'],
                    'circuit_id' => $order['circuit_id'],
                    'user_id'=> $value['user_id'],
                    'contacts_id' => $value['contacts_id'],
                    'name' => $value['name'],
                    'telephone' => $value['telephone'],
                    'id_card' => $value['id_card'],
                    'status' => 1,
                    'addtime' => $time,
                    'updatetime' => $time
                ];
                Cm::$db->insert("order_passenger", $mdata);
            }
            Cm::$db->update("order_change_audit",['change_id'=>$changeid,'updatetime'=> $time],"id={$auditid}");
			/*发送模板消息*/
			$TemplateData = [
	            'openid' => $this->openid,
	            'old_order_id' => $order_id,
	            'changeid' => $changeid,
	        ];
			Cm::$libs->wechat->sendTemplate('change',$TemplateData);
        }else{
        	Cm::$db->delete("order_change_audit","id={$auditid}");
            Cm::$res->error("改签失败,无法生成新订单");
        }  
    }

	/*
	*解密
	*/
	private function refundDecrypt($str){
		$decrypt = base64_decode($str,true);
		$config = Yii::$app->params['wechat']['open'];
		$key = md5($config['mch_key']);
		return openssl_decrypt($decrypt, 'aes-256-ecb', $key , OPENSSL_RAW_DATA);
	}

	/*
	*检验是否能退款
	*/
	private function checkrefund($departuretime,$nowtime,$circuit_id){
		/*是否能退票*/
		$isok = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=7 AND  circuit_id={$circuit_id} AND status=1");
		if(empty($isok)){
			$isok = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=7 AND circuit_id=0 AND status=1");
			$time = empty($isok) ? 0 : (int)$isok['value'];
		}else{
			$time = (int)$isok['value'];
		}
		$departuretime = strtotime($departuretime);
		$checktime = $departuretime-$time*60;
		$nowtime = strtotime($nowtime);
		return  ['status'=>$nowtime > $departuretime && $nowtime > $departuretime ? 0 : 1,'time'=>$time];
	}

	/*
	*检验是否能进行改签
	*/
	private function checkchange($order_id,$departuretime,$nowtime,$circuit_id){
		$haschange = $this->ischangeorder($order_id);
		if($haschange['status'] == 1){
			/*改签上限*/
			$ishas = Cm::$db->one("SELECT * FROM config_setting WHERE `group`='sys' AND `key`='sys_order_change' AND status=1");
			$changenum = empty($ishas) ? 0 : $ishas['value'];
			if($changenum > 0 && $changenum<=$haschange['changenum']){
				return ['status'=>3,'time'=>'','changenum' =>$haschange['changenum']];
			}
		}
		$exitchange = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=5 AND  circuit_id={$circuit_id} AND status=1");
		if(empty($excicuit)){
			$exitchange = Cm::$db->one("SELECT `value` FROM rule_setting WHERE type=5 AND circuit_id=0 AND status=1");
			$time = empty($exitchange) ? 0 : (int)$exitchange['value'];
		}else{
			$time = (int)$exitchange['value'];
		}
		$departuretime = strtotime($departuretime);
		$checktime = $departuretime-$time*60;
		$nowtime = strtotime($nowtime);
		return  ['status'=>$nowtime > $departuretime && $nowtime > $departuretime ? 0 : 1,'time'=>$time,'order_id'=>$haschange['order_id']];
	}

	/*是否是改签新单*/
	private function ischangeorder($order_id){
		$haschange = Cm::$db->one("SELECT a.id,a.first_order_id AS order_id,(SELECT CONCAT_WS(',',order_number,pay_price) AS firstorder FROM `order` WHERE id=a.first_order_id) AS firstorder,(SELECT COUNT(id) AS num FROM order_change_audit WHERE first_order_id=a.first_order_id AND status=1) AS changenum FROM order_change_audit a WHERE a.change_id={$order_id} AND a.status=1");
		$firstorder = empty($haschange) ? '' : explode(",", $haschange['firstorder']);
		return ['status'=>empty($haschange) ? 0 : 1,'order_number' => empty($haschange) ? '' : $firstorder[0],'pay_price'=>empty($haschange) ? '' : $firstorder[1],'order_id' => empty($haschange) ? '' : $haschange['order_id'],'changenum'=>empty($haschange) ? 0 : $haschange['changenum']];
	}

	/*
	*生成订单号
	*/
	private  function getorderanumber($shift_id,$circuit_id,$timestr){
		$sql = "SELECT order_number
		        FROM `order` 
				WHERE shift_id={$shift_id} AND circuit_id={$circuit_id}
				AND TO_DAYS(addtime)=TO_DAYS('{$timestr}') ORDER BY id DESC";
        $order = Cm::$db->one($sql);

        $order_number = "";
        $ctime = date('ymd', strtotime($timestr));
        if (isset($order['order_number'])) {
            $order_number = $order['order_number'];
            if (substr($order_number, 0, 1) == 'M') {
                $order_number = str_replace('M', '', $order_number);
            }
            $number =  (((int)substr($order_number, -4)) + 1);
            $order_number =  $shift_id . $circuit_id . $ctime .sprintf("%04d", $number);
        } else {
            $record_id = 1 % 10000;
            $order_number = $shift_id . $circuit_id . $ctime . sprintf("%04d", $record_id);
        }
        return $order_number;
	}

	/*
	*须知数据
	*/
	private function getNoticeData($key){
		$sql = "SELECT value FROM config_setting WHERE `group`='sys' AND `key`='{$key}' AND  status=1";
		$data = Cm::$db->one($sql);
		$resdata = [];
		if(!empty($data)){
			$resdata = htmlspecialchars_decode(str_replace(array("\r\n", "\r", "\n"), "", $data['value']));
		}
		return $resdata;
	}

	/*
	*刷新订单
	*/
	private function refreshorder(){
		$time = time();
		/*待支付的订单 更新已失效  1*/
		$this->changeorderstatus(1,$time,5);
		/*已支付的订单 更新已发车 3*/
		//$this->changeorderstatus(3,$time,3);
		/*已支付的订单 更新已完成 4*/	
		//$this->changeorderstatus(4,$time,4);
	}

	/*更新订单状态*/
	private function changeorderstatus($type,$time,$status){
		$setting = Cm::$db->all("SELECT `value`,circuit_id FROM rule_setting WHERE type={$type} AND status=1");
		$timestr = date("Y-m-d H:i:s",$time);
		$where = $type == 1 ? " AND a.order_status=0 " : ($type==3?" AND a.order_status IN (1,2)" : " AND a.order_status IN (1,2,3) ");
		if(!empty($setting)){
			$settingarr = [];
			foreach ($setting as $key => $value) {
				$settingarr[$value['circuit_id']] = $value['value'];
			}
			$list = Cm::$db->all("SELECT a.id,a.addtime,a.circuit_id,b.departuretime FROM `order` a 
								LEFT JOIN user u ON u.id=a.user_id 
								LEFT JOIN shift b ON b.id=a.shift_id 
								WHERE u.openid='{$this->openid}' {$where} AND a.status=1");
			if(!empty($list)){
				foreach ($list as $key => $value) {
					$setting_time = isset($settingarr[$value['circuit_id']]) ? $settingarr[$value['circuit_id']] : (isset($settingarr[0]) ? $settingarr[0] : 0);
					$ordertime = $type==1 ? strtotime($value['addtime'])+$setting_time*60 : strtotime($value['departuretime'])+$setting_time*60;
					if($setting_time != 0 && $ordertime<=$time){
						$mdata = [
							'order_status' => $status,
							'updatetime' => $timestr
						];
						Cm::$db->update("order",$mdata," id={$value['id']}");
					} 
				}
			}
		}
	}

	/*
	*添加二维码
	*/
	public function addordercode($orderid){
		$codenum = Cm::$code->jia($orderid, true);
		$url = BASE_URL . Url::to(['/inspector/#/orderDetails', 'code' => urlencode($codenum)]);
		$codeimg = BASE_PATH."upload/ordercode/".$orderid.".png";
    	Cm::$util->QRcode($url, 3.5, $codeimg);
		$codedata = [
			'codenum' => $codenum,
			'codeimg' => BASE_URL."/upload/ordercode/".$orderid.".png"
		];
		Cm::$db->update("order",$codedata,"id={$orderid}");
		return $codedata;
	}

	/*
	*支付回调log
	*/
	private function notifylog($data, $type = 'notify')
    {
        Cm::$app->log->common($type, $data);
    }

    /*
    *签名
    */
    private function checkSign($data)
    {
        $flag = false;

        if (isset($data['appid']) && isset($data['sign'])) {
			$config = Yii::$app->params['wechat']['open'];
            $mchKey = isset($config['mch_key']) ? $config['mch_key'] : '';

            ksort($data);
            $string = $this->ToUrlParams($data);
            //签名步骤二：在string后加入KEY
            $string = $string . "&key=" . $mchKey;
            //签名步骤三：MD5加密
            $string = md5($string);
            //签名步骤四：所有字符转为大写
            $makeSign = strtoupper($string);

            if ($data['sign'] == $makeSign)
                $flag = true;

        }

        $rowData = array(
            "out_trade_no" => isset($data['out_trade_no']) ? $data['out_trade_no'] : '',
            "appid" => isset($data['appid']) ? $data['appid'] : '',
            "openid" => isset($data['openid']) ? $data['openid'] : '',
            "cash_fee" => isset($data['cash_fee']) ? $data['cash_fee'] : '',
            "sign" => isset($data['sign']) ? $data['sign'] : '',
            "content" => json_encode($data),
            "check_sign" => $flag ? 1 : 0,
            "make_sign" => $makeSign,
            "addtime" => date('Y-m-d H:i:s')
        );
        $this->notifylog($rowData,'notify-checkSign');

        return $flag;
    }

    /**
     * 格式化参数格式化成url参数
     */
    private function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }
}